package com.xiaoxiong.newmyscse;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.xiaoxiong.newmyscse.bean.ResultData;
import com.xiaoxiong.newmyscse.intef.ResultInterface;
import com.xiaoxiong.newmyscse.net.MyHttpPost;

/**
 * 
 * @ClassName: MainActivity 
 * @Description: TODO
 * @author smile
 * @date 2016年5月17日 上午1:34:53 
 *
 */
public class MainActivity extends Activity implements ResultInterface {

	private EditText usernameEditText;// 学号输入框
	private EditText passwordEditText;// 密码输入框
	private Button loginButton;// 登录按钮
	private Button getAllCourseButton;// 获取全校课程信息按钮
	private TextView showAllCourseTextView;// 显示全校课程信息按钮
	private ProgressBar loadingBar;//加载中的
	private MyHttpPost myHttpPost;// 网络请求
	private static int whichPost;// 表示谁发起请求，请求结果发给它处理
	private String username;// 学号
	private String password;// 密码
	private Map<String, String> cookie;// cookie
	private Map<String, String> hidden;// 隐藏域

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		cookie = new HashMap<String, String>();
		hidden = new HashMap<String, String>();
		// 创建MyHttpPost
		myHttpPost = new MyHttpPost(this);
		// 获取各个组件
		usernameEditText = (EditText) findViewById(R.id.username);
		passwordEditText = (EditText) findViewById(R.id.password);
		loginButton = (Button) findViewById(R.id.login);
		getAllCourseButton = (Button) findViewById(R.id.getallcourse);
		showAllCourseTextView = (TextView) findViewById(R.id.showallcourse);
		loadingBar = (ProgressBar) findViewById(R.id.loading);
		// 还没有发送请求，所以先把它隐藏掉
		loadingBar.setVisibility(View.GONE);
		// 监听按钮点击事件
		loginButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// 获取学号和密码输入框中的值
				username = usernameEditText.getText().toString();
				password = passwordEditText.getText().toString();
				// 先判断是否有输入学号和密码
				if (username.equals("") || password.equals("")) {
					Toast.makeText(getApplicationContext(), "学号和密码不能为空！",
							Toast.LENGTH_SHORT).show();
				} else {
					//开始登录
					startLogin();
				}
			}
		});
		// 还没有登录，不能获取全校课程信息，所以先把这个按钮隐藏掉
		getAllCourseButton.setVisibility(View.GONE);
		getAllCourseButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				getAllCourse();
			}
		});
	}

	/**
	 * 
	* @Title: startLogin 
	* @Description: 开始登录
	* @param 
	* @return void
	* @throws
	 */
	private void startLogin() {
		//将加载中的bar显示出来
		loadingBar.setVisibility(View.VISIBLE);
		// 设置按钮上显示的内容
		loginButton.setText("登录中...");
		// 设置按钮不可点击
		loginButton.setClickable(false);
		// 标志设为1， 表示现在请求获取隐藏域
		whichPost = 1;
		// 先请求LoginUrl这个网址，从返回结果中取出隐藏域
		myHttpPost.setPostUrl(SchoolUrl.LoginUrl);
		// 开始请求
		myHttpPost.post();
	}

	/**
	 * 
	* @Title: getAllCourse 
	* @Description: 开始获取全校课程信息
	* @param 
	* @return void
	* @throws
	 */
	private void getAllCourse() {
		//将加载中的bar显示出来
		loadingBar.setVisibility(View.VISIBLE);
		// 设置按钮上显示的内容
		getAllCourseButton.setText("获取中...");
		// 设置按钮不可点击
		getAllCourseButton.setClickable(false);
		// 标志设为4， 表示现在请求获取全校课程信息
		whichPost = 4;
		// 先请求LoginUrl这个网址，从返回结果中取出隐藏域
		myHttpPost.setPostUrl(SchoolUrl.urls.get("selectclassallcourse_view"));
		// 设置cookie,通过cookie就可以拿到全校课程信息了，不再需要提交学号跟密码了
		myHttpPost.setPostParams(cookie);
		// 开始请求
		myHttpPost.post();
	}

	@Override
	public void resultOfPost(ResultData resultData) {

		if (resultData.getStatus()) {
			// 请求结果状态标志为true，说明请求成功，在这里处理数据
			switch (whichPost) {
			case 1:
				// 现在是处理返回的内容，获取隐藏域
				dealHidden(resultData.getContent());
				// 标志设为2，表示现在请求LoginCheckUrl这个网址获取cookie,这里需要提交学号、密码、隐藏域参数
				whichPost = 2;
				myHttpPost.setPostUrl(SchoolUrl.LoginCheckUrl);
				Map<String, String> param = new HashMap<String, String>();
				param.put("username", username);
				param.put("password", password);
				param.put(hidden.get("name"), hidden.get("value"));
				myHttpPost.setPostParams(param);
				// 设置需要获取cookie
				myHttpPost.setNeedGetCookies(true);
				// 开始请求
				myHttpPost.post();

				break;
			case 2:
				// 到了这一步不一定拿到cookie，因为提交的学号或密码可能有错，这里要先判断一下
				// Log.d("cookie", resultData.getContent());
				if (resultData.getContent().indexOf("sise/index.jsp") != -1) {
					// 现在已经获取cookie，先保存起来，通过cookie就可以去获取各种信息了
					// 先清除一下里面的数据，避免重复
					cookie.clear();
					cookie.put(resultData.getCookieName(),
							resultData.getCookieValue());
					// 已经拿到cookie，后面不需要再拿了，设置为false
					myHttpPost.setNeedGetCookies(false);
					// 标志设为3，表示现在请求SelectClassUrl这个网址获取,这里只需要提交cookie就可以了
					// 请求这个网址，是为了拿到获取各种信息的网址所需要的学生id等值
					whichPost = 3;
					myHttpPost.setPostUrl(SchoolUrl.SelectClassUrl);
					myHttpPost.setPostParams(cookie);
					myHttpPost.post();
				} else {
					Toast.makeText(this, "学号或密码错误", Toast.LENGTH_SHORT).show();
					// 请求完成，所以先把它隐藏掉
					loadingBar.setVisibility(View.GONE);
					// 设置按钮上显示的内容
					loginButton.setText("登录");
					// 设置按钮可点击
					loginButton.setClickable(true);
					// 既然登录失败，那需要重新登录，就需要重新获取cookie，所以设为true
					myHttpPost.setNeedGetCookies(true);
				}

				break;
			case 3:
				// 请求完成，所以先把它隐藏掉
				loadingBar.setVisibility(View.GONE);
				// 现在已经拿到包含各种信息的网址的网页内容了
				// Log.d("value", resultData.getContent());
				// 设置按钮上显示的内容
				loginButton.setText("登录成功");
				usernameEditText.setVisibility(View.GONE);
				passwordEditText.setVisibility(View.GONE);
				// 接下来从网页中取出每个网址
				dealAllUrl(resultData.getContent());
				// 把按钮显示出来
				getAllCourseButton.setVisibility(View.VISIBLE);

				break;
			case 4:
				// 请求完成，所以先把它隐藏掉
				loadingBar.setVisibility(View.GONE);
				// 现在请求成功，返回的数据中就包含全校课程信息
				// Log.d("value", resultData.getContent());
				// 设置按钮上显示的内容
				getAllCourseButton.setText("获取成功");
				// 下面我们要把信息拿出来
				dealAllCourse(resultData.getContent());

				break;

			default:
				break;
			}
		} else {
			// 请求失败
			Toast.makeText(this, "请求失败！", Toast.LENGTH_SHORT).show();
			// 请求完成，所以先把它隐藏掉
			loadingBar.setVisibility(View.GONE);
			// 小于4，说明是在登录部分请求失败
			if (whichPost < 4) {
				// 设置按钮上显示的内容
				loginButton.setText("登录");
				// 设置按钮可点击
				loginButton.setClickable(true);
				// 既然登录失败，那需要重新登录，就需要重新获取cookie，所以设为true
				myHttpPost.setNeedGetCookies(true);
			} else if (whichPost == 4) {
				// 等于4说明是在获取全校课程信息时请求失败
				// 设置按钮上显示的内容
				getAllCourseButton.setText("获取全校课程信息");
				// 设置按钮可点击
				getAllCourseButton.setClickable(true);
			}
		}
	}

	/**
	 * 
	 * @Title: dealHidden
	 * @Description: 获取隐藏域
	 * @param @param result
	 * @return void
	 * @throws
	 */
	private void dealHidden(String result) {
		// Log.d("result", result);
		// 服务器返回的是整个html页面代码，我们处理成String类型了，所以这里要用到Jsoup封装成Document类型
		Document html = Jsoup.parse(result);
		// 根据form表单解析
		Elements element = html.getElementsByTag("form");
		// 获取表单中第一个节点的name值
		String name = element.get(0).childNode(1).attr("name");
		// 获取表单中第一个节点的value值
		String value = element.get(0).childNode(1).attr("value");
		// 保存隐藏域
		// 先清除一下里面的数据，避免重复
		hidden.clear();
		hidden.put("name", name);
		hidden.put("value", value);

	}

	/**
	 * 
	 * @Title: dealStudentId
	 * @Description: 获取各个网址
	 * @param @param result
	 * @return void
	 * @throws
	 */
	private void dealAllUrl(String result) {

		// 下面对应的地址为：
		// urlName[0] : courseview ：个人信息
		// urlName[1] : student_schedular ：课程表
		// urlName[2] : exam ：考试时间表
		// urlName[3] : attendance ：考勤信息
		// urlName[4] : commonresult ：平时成绩
		// urlName[5] : encourage_punish ：奖惩记录
		// urlName[6] : teaching_material_view ：教材信息
		// urlName[7] : tuitionUseList ：预交费用
		// urlName[8] : studentBalance ：学生交费
		// urlName[9] : repair ：网上报修
		// urlName[10] : selectclasscourse_view ：查看开设课程
		// urlName[11] : selectclassallcourse_view ：全校课程信息
		// urlName[12] : studentselectteam_item ：选课选班
		// urlName[13] : select_tutorial_class ：辅导班选班
		// urlName[14] : rankexamsign ：等级考试报名
		// urlName[15] : studentEvaluate ：教学评价
		// urlName[16] : managerEvaluate ：学习导师评价
		// urlName[17] : counsellorEvaluat ：辅导员评价
		// urlName[18] : researchquestion ：问卷调查
		// urlName[19] : suggestcourse ：课堂教学意见和建议
		// urlName[20] : career_ws ：职业生涯规划
		// urlName[21] : awards ：评奖评优申请报名
		// urlName[22] : lateStudent ：晚归、违规用电记录
		String[] urlName = { "courseview", "student_schedular", "exam",
				"attendance", "commonresult", "encourage_punish",
				"teaching_material_view", "tuitionUseList", "studentBalance",
				"repair", "selectclasscourse_view",
				"selectclassallcourse_view", "studentselectteam_item",
				"select_tutorial_class", "rankexamsign", "studentEvaluate",
				"managerEvaluate", "counsellorEvaluat", "researchquestion",
				"suggestcourse", "career_ws", "awards", "lateStudent" };

		// 用正则表达式从得到的网页中取出所有类似window.location='../../../../../SISEWeb/pub...或window.top.location='/sise/...的字符串
		Matcher m1 = Pattern.compile("window(\\.top|\\.location)(.*)").matcher(
				result);
		// 取出来的这样的字符串有23个，但是有一些我们暂时不用的，不过没关系，全都保存起来，要用哪个就用哪个
		int i = 0;
		while (m1.find()) {
			// 先处理找到的每个字符串，因为我们匹配出来的是类似这样的window.location='/sise/module/rankexamsign/rankexamsign.jsp';"
			// 我们要取出后面那部分/sise/module/rankexamsign/rankexamsign.jsp，再加上前缀即SchoolUrl类里面的baseUrl
			// 即这样组合SchoolUrl.baseUrl +
			// "/sise/module/rankexamsign/rankexamsign.jsp"
			// 然后把urlName存为key，找到的每个字符串都存为值，以后要用到可以通过key找到对应的网址
			// 以上面那个网址为例子就是这样存的：
			// "rankexamsign" :
			// "SchoolUrl.baseUrl + '/sise/module/rankexamsign/rankexamsign.jsp'"
			// 同样用正则表达式匹配
			Matcher m2 = Pattern.compile("(/sise|/SISE)(.*)\\'").matcher(
					m1.group());
			// 如果找得到
			if (m2.find()) {
				// 把找到的字符串中的所有'去掉
				// 因为找出来的是这样的：/sise/module/rankexamsign/rankexamsign.jsp'
				// 后面那个'需要去掉
				String urlString = m2.group().replace("'", "");
				// Log.d("url", SchoolUrl.baseUrl + urlString);

				SchoolUrl.urls.put(urlName[i++], SchoolUrl.baseUrl + urlString);
			}
		}
	}

	/**
	 * 
	* @Title: dealAllCourse 
	* @Description: 处理请求返回的数据，取出全校课程信息
	* @param @param result
	* @return void
	* @throws
	 */
	private void dealAllCourse(String result) {
		// 把result封装成Document对象
		Document doc = Jsoup.parse(result);
		// 通过class名，爬下来的是一个网页，里面肯定有css，有类名等 所以可以通过类名分离数据，但不一定是根据类名，可能要根据标签、其他标志等
		// Document对象有提供好几种方法，这个要自己根据网页的代码去分析使用那种方法最好
		// 我这里是根据类名，因为我发现课程信息这个网页通过用类名分离数据，可以完全过滤掉其他所有没用的信息
		Elements element = doc.getElementsByClass("tablebody");
		StringBuilder sb3 = new StringBuilder();
		int flag = 0;

		// 下面是分离好的信息，可以通过这种方法遍历，看看分离好的信息是什么
		for (Element links : element) {
			String title = links.text();
			sb3.append(title);
			// 以下几行是我知道分离好的信息是什么，进而把数据集中分类用到的， 并不是所有网页的数据都可以这么写的，要根据具体数据去分析
			flag++;
			if (flag == 5) {
				flag = 0;
				sb3.append("\n");
			} else {
				sb3.append("-");
			}
		}
		// 将结果显示出来
		showAllCourseTextView.setText(sb3);
	}
}
